package com.xiaoshuidi.cloud.module.rooms.mq.listener;

import cn.hutool.core.util.IdUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.fastjson.JSON;
import com.xiaoshuidi.cloud.framework.common.exception.ServiceException;
import com.xiaoshuidi.cloud.framework.common.exception.enums.GlobalErrorCodeConstants;
import com.xiaoshuidi.cloud.module.rooms.controller.admin.roomhouse.vo.PartLeaseTemplateVo;
import com.xiaoshuidi.cloud.module.rooms.enums.RoomTypeEnum;
import com.xiaoshuidi.cloud.module.rooms.service.RoomHouseService;
import com.xiaoshuidi.cloud.module.rooms.valid.PartLeaseImportValid;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 合租房源导入 listener
 *
 * @Author Summer
 * @date 2023/5/22
 */
@Slf4j
@AllArgsConstructor
public class PartListener extends AbstractExcelListener<PartLeaseTemplateVo> {
    private String esKey;
    private Long apartmentId;
    private Long tenantId;
    private Long userId;
    private AtomicInteger count;
    private RoomHouseService roomHouseService;

    @Override
    public void invoke(PartLeaseTemplateVo data, AnalysisContext context) {
        count.incrementAndGet();
        log.info("part解析到一条数据:{}", JSON.toJSONString(data));
        PartLeaseImportValid partLeaseImportValid = new PartLeaseImportValid();
        boolean valid = true;
        HashMap<String, String> errorMap = new HashMap<>();
        try {
            valid = partLeaseImportValid.valid(data, errorMap);
        } catch (Exception e) {
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), "第" + count + "行" + e.getMessage());
        }
        if (!valid) {
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), "第" + count + "行" + JSON.toJSONString(errorMap.values()));
        }
        cachedDataList.add(data);
    }

    @Override
    public void saveData() {
        if (this.cachedDataList.size() > 0) {
            List<PartLeaseTemplateVo> temps = new ArrayList<>();
            Map<String, List<PartLeaseTemplateVo>> listMap = this.cachedDataList.stream().collect(Collectors.groupingBy(p -> fetchGroupKey(p)));
            //校验户型+1=分组条数
            for (List<PartLeaseTemplateVo> list : listMap.values()) {
                PartLeaseTemplateVo part = list.get(0);
                //查看房间类型不是公共区域的房间记录总和是不是和户型相等
                List<PartLeaseTemplateVo> rooms = list.stream().filter(r -> r.getRoomType().equals(RoomTypeEnum.ZW.getName())
                        || r.getRoomType().equals(RoomTypeEnum.CW.getName())
                        || r.getRoomType().equals(RoomTypeEnum.KW.getName())).collect(Collectors.toList());
                if (rooms.size() != part.getRoomNum().intValue()) {
                    throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), "合租户型数据有误!");
                }
                //转为map，键为房号，值为该键存在的次数（使用"merge"操作：Integer::sum）,利用过滤，获取值大于1的数据
                List<String> noList = list.stream().map(PartLeaseTemplateVo::getNo)
                        .collect(Collectors.toMap(e -> e, e -> 1, Integer::sum))
                        .entrySet()
                        .stream()
                        .filter(entry -> entry.getValue() > 1)
                        .map(Map.Entry::getKey)
                        .collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(noList)) {
                    throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), fetchGroupKey(part) + "合租房号数据有重复!");
                }
                //查看有没有录入公共区域数据，如果有就用录入的，如果没有就补充一条
                Optional<PartLeaseTemplateVo> ggqy = list.stream().filter(r -> r.getRoomType().equals(RoomTypeEnum.GGQY.getName())).findFirst();
                if (!ggqy.isPresent()) {
                    PartLeaseTemplateVo ggquRoom = new PartLeaseTemplateVo();
                    BeanUtils.copyProperties(part, ggquRoom);
                    ggquRoom.setHouseNo(ggquRoom.getHouseNo()+"公区");
                    ggquRoom.setRoomType(RoomTypeEnum.GGQY.getName());
                    list.add(ggquRoom);
                }
                //校验全部完成开始写数据
                //添加房源信息
                //1.设置主房源信息
                PartLeaseTemplateVo mainRoom = new PartLeaseTemplateVo();
                BeanUtils.copyProperties(part, mainRoom);
                mainRoom.setRoomType("主房源");
                mainRoom.setId(IdUtil.getSnowflakeNextId());

                //把导入的记录的id生成好，并且赋值supper_id
                list = list.stream().peek(r -> {
                    r.setId(IdUtil.getSnowflakeNextId());
                    r.setSupperId(mainRoom.getId());
                }).collect(Collectors.toList());

                //主房源信息添加进分组list
                list.add(mainRoom);
                list.forEach(r -> temps.add(r));
            }

            try {
                roomHouseService.batchNoConcentratedAdd(esKey,temps, apartmentId, tenantId, userId, "part");//合租
            } catch (Exception e) {
                throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(), e.getMessage());
            }
        }
    }

    /**
     * 将区+"_"+街道+"_"+地址+"_"+小区"_"+栋+"_"+单元+"_"+房号 和产权人信息作为组合属性判断合租的是不是一套房源
     *
     * @param part
     * @return
     */
    private static String fetchGroupKey(PartLeaseTemplateVo part) {
        return part.getDistrict() + "_" + part.getStreet() + "_" + part.getAddress()
                + "_" + part.getArea() + "_" + part.getBuildingNo() + "_" + part.getUnitNo()
                + "_" + part.getHouseNo() + "_" + part.getOwnerName() + "_" + part.getCardType()
                + "_" + part.getCardNo() + "_" + part.getTelPhone() + "_" + part.getPropertyType()
                + "_" + part.getPropertyNo() + "_" + part.getPropertyStreet() + "_" + part.getRegisterType()
                + "_" + part.getHouseStructure() + "_" + part.getDecoration();
    }
}
